#include "ddl.h"
#include <rtthread.h>

static void SysGpio_Init(void);

int32_t main(void)
{
    SysGpio_Init();

    while (1)
    {
        Gpio_SetIO(GpioPortA, GpioPin1);
        rt_thread_mdelay(500);
        Gpio_ClrIO(GpioPortA, GpioPin1);
        rt_thread_mdelay(500);
    }
}

static void SysGpio_Init(void)
{
    stc_gpio_config_t pstcGpioCfg;
    
    ///< 打开GPIO外设时钟门控
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
    
    ///< 端口配置->推挽输出
    pstcGpioCfg.enDir  = GpioDirOut;
    pstcGpioCfg.enDrv  = GpioDrvH;
    pstcGpioCfg.enPuPd = GpioNoPuPd;
    pstcGpioCfg.enOD   = GpioOdDisable;
    pstcGpioCfg.enCtrlMode = GpioAHB;
    
    Gpio_Init(GpioPortA, GpioPin1, &pstcGpioCfg);
}

void SysClock_Init(void)
{
    stc_sysctrl_clk_config_t stcCfg;
    stc_sysctrl_pll_config_t stcPLLCfg;    
    
    ///< 开启FLASH外设时钟
    Sysctrl_SetPeripheralGate(SysctrlPeripheralFlash, TRUE);
    
    ///< 因将要倍频的PLL作为系统时钟HCLK会达到48MHz：所以此处预先设置FLASH 读等待周期为1 cycle(默认值为0 cycle)
    Flash_WaitCycle(FlashWaitCycle1);
    
    ///< 时钟初始化前，优先设置要使用的时钟源：此处配置PLL
    Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz);             //PLL使用RCH作为时钟源，因此需要先设置RCH    
    
    stcPLLCfg.enInFreq    = SysctrlPllInFreq4_6MHz;     //RCH 4MHz
    stcPLLCfg.enOutFreq   = SysctrlPllOutFreq36_48MHz;  //PLL 输出48MHz
    stcPLLCfg.enPllClkSrc = SysctrlPllRch;              //输入时钟源选择RCH
    stcPLLCfg.enPllMul    = SysctrlPllMul12;            //4MHz x 12 = 48MHz
    Sysctrl_SetPLLFreq(&stcPLLCfg);
    
    ///< 选择PLL作为HCLK时钟源;
    stcCfg.enClkSrc  = SysctrlClkPLL;
    ///< HCLK SYSCLK/1
    stcCfg.enHClkDiv = SysctrlHclkDiv1;
    ///< PCLK 为HCLK/2
    stcCfg.enPClkDiv = SysctrlPclkDiv2;
    ///< 系统时钟初始化
    Sysctrl_ClkInit(&stcCfg);
}

int Usart_DeBug_Init(void)
{
    stc_gpio_config_t       stcGpioCfg;
    stc_uart_config_t       stcConfig;
    stc_uart_irq_cb_t       stcUartIrqCb;
    stc_uart_multimode_t    stcMulti;
    stc_uart_baud_t         stcBaud;

    DDL_ZERO_STRUCT(stcGpioCfg);
    DDL_ZERO_STRUCT(stcConfig);
    DDL_ZERO_STRUCT(stcUartIrqCb);
    DDL_ZERO_STRUCT(stcMulti);
    DDL_ZERO_STRUCT(stcBaud);

    // 外设时钟使能
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 
    Sysctrl_SetPeripheralGate(SysctrlPeripheralUart0, TRUE);

    /** 端口初始化
     * 
     *  Tx  PA9
     *  Rx  PA10
     * */
    stcGpioCfg.enDir = GpioDirOut;
    Gpio_Init(GpioPortA, GpioPin9, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin9, GpioAf1);

    stcGpioCfg.enDir = GpioDirIn;
    Gpio_Init(GpioPortA, GpioPin10, &stcGpioCfg);
    Gpio_SetAfMode(GpioPortA, GpioPin10, GpioAf1);

    // 串口配置
    stcUartIrqCb.pfnRxIrqCb   = NULL;
    stcUartIrqCb.pfnTxIrqCb   = NULL;
    stcUartIrqCb.pfnRxFEIrqCb = NULL;
    stcUartIrqCb.pfnPEIrqCb   = NULL;
    stcUartIrqCb.pfnCtsIrqCb  = NULL;
    stcConfig.pstcIrqCb  = &stcUartIrqCb;
    stcConfig.bTouchNvic = FALSE;
    if (TRUE == stcConfig.bTouchNvic)
    {
        EnableNvic(UART0_IRQn, IrqLevel3, TRUE);
    }

    stcConfig.enRunMode = UartMode1;
    stcConfig.enStopBit = Uart1bit;

    // 工作模式
    stcMulti.enMulti_mode = UartNormal;         //正常工作模式
    Uart_SetMultiMode(UARTCH0, &stcMulti);      //多主机单独配置
    Uart_SetMMDOrCk(UARTCH0, UartDataOrAddr);   //无校验
    Uart_Init(UARTCH0, &stcConfig);             //串口初始化函数

    // 波特率设置
    Uart_SetClkDiv(UARTCH0, Uart16Or32Div);
    stcBaud.u32Pclk   = Sysctrl_GetPClkFreq();
    stcBaud.enRunMode = UartMode1;
    stcBaud.u32Baud   = 115200;
    Uart_SetBaud(UARTCH0, Uart_CalScnt(UARTCH0, &stcBaud));

    Uart_ClrStatus(UARTCH0, UartTC);  //清发送请求
    Uart_ClrStatus(UARTCH0, UartRC);  //清接收请求
    Uart_EnableFunc(UARTCH0, UartRx); //使能收发

    return 0;
}
INIT_BOARD_EXPORT(Usart_DeBug_Init);

//支持控制台
void rt_hw_console_output(const char *str)
{
    rt_size_t i = 0, size = 0;

    rt_enter_critical();

    size = rt_strlen(str);
    for (i = 0; i < size; i++)
    {
        if (str[i] == '\n')
        {
            while(FALSE == Uart_GetStatus(UARTCH0, UartTxe));
            M0P_UART0->SBUF_f.DATA = (char)'\r';
        }
        
        while(FALSE == Uart_GetStatus(UARTCH0, UartTxe));
        M0P_UART0->SBUF_f.DATA = str[i];
    }

    rt_exit_critical();
}

char rt_hw_console_getchar(void)
{
    int ch = -1;

    if (Uart_GetStatus(UARTCH0, UartRC)) //接收到数据
    {
        Uart_ClrStatus(UARTCH0, UartRC);
        ch = Uart_ReceiveData(UARTCH0); //接收数据
    }
    else
    {
        if ((Uart_GetStatus(UARTCH0, UartFE)) || (Uart_GetStatus(UARTCH0, UartPE))) //错误请求
        {
            Uart_ClrStatus(UARTCH0, UartFE); //清除帧错误标记
            Uart_ClrStatus(UARTCH0, UartPE); //清除奇偶校验错误标记
        }
        rt_thread_mdelay(10);
    }

    return ch;
}

void rt_hw_us_delay(rt_uint32_t us)
{
    rt_uint32_t delta;

    us = us * (SysTick->LOAD / (1000000 / RT_TICK_PER_SECOND));
    delta = SysTick->VAL;
    
    while (delta - SysTick->VAL < us);
}
